import 'package:dio/dio.dart';
import 'package:flutter_enjoy_plus/constants/index.dart';
import 'package:flutter_enjoy_plus/utils/Toast.dart';

// 请求类的单例模式
class RequestDio {
  // 有个地方可以设置dio的基础地址
  final Dio _dio = Dio();

  // 构造器
  RequestDio() {
    // 针对dio的基础地址进行设置

    // 设置基础地址
    // _dio.options.baseUrl = GlobalVariable.BASE_URL;
    // 设置接收超时时间
    // _dio.options.receiveTimeout = const Duration(seconds: GlobalVariable.NET_WORK_TIME);
    // 设置发送超时时间
    // _dio.options.sendTimeout = const Duration(seconds: GlobalVariable.NET_WORK_TIME);

    // .. 和 . 区别
    // . 返回对应的执行结果
    // .. 返回原对象
    _dio
      ..options.baseUrl = GlobalVariable.BASE_URL
      ..options.receiveTimeout =
          const Duration(seconds: GlobalVariable.NET_WORK_TIME)
      ..options.sendTimeout =
          const Duration(seconds: GlobalVariable.NET_WORK_TIME);

    // axios 和 rcp的拦截器
    // 添加请求和响应拦截器
    _registerInterceptors(); // 注册拦截器
  }

  // 拦截器的注册
  _registerInterceptors() {
    _dio.interceptors.add(
      // handler
      // 1. handler.next(): 正常流程，将控制器传递到下一流程。
      // 2. handler.resolve(): 返回自定义响应， 非正常流程。
      // 3. handler.reject(): 抛出一个错误，终结正常请求流程。

      InterceptorsWrapper(
          // 请求拦截器： 在请求发送前可以为请求参数添加请求头等请求信息
          onRequest: (request, handler) {
        // request里面是请求参数
        handler.next(request);
      },
          // 响应拦截器： http 状态码正常，可以检查业务状态码是否正常。
          onResponse: (response, handler) {
        // response是响应结果
        if (response.statusCode! >= 200 && response.statusCode! < 300) {
          handler.next(response); // 处理数据  这里可以处理错误
        } else {
          // 加401判断
          PromptAction.showError(response.statusMessage!); // 处理http 请求的问题
          handler.reject(DioException(requestOptions: response.requestOptions));
        }
      },
          // 错误拦截器： http 状态码报错。
          onError: (exception, handler) {
        // exception.response 获取响应数据
        // exception.requestOption 获取请求数据
        handler.next(exception); // 抛出问题
      }),
    );
  }

  // 获取方法
  Future get(String url, {Map<String, dynamic>? params}) async {
    final result = await _dio.get(url, queryParameters: params);
    // 需要对数据进行二次处理
    return _handleResponse(result);
  }

  Future post(String url, {Map<String, dynamic>? data}) async {
    final result = await _dio.post(url, data: data);
    // 需要对数据进行二次处理
    return _handleResponse(result);
  }

  Future delete(String url,
      {Map<String, dynamic>? data, Map<String, dynamic>? params}) async {
    final result = await _dio.delete(url, queryParameters: params, data: data);
    // 需要对数据进行二次处理
    return _handleResponse(result);
  }

  Future put(String url,
      {Map<String, dynamic>? data, Map<String, dynamic>? params}) async {
    final result = await _dio.put(url, queryParameters: params, data: data);
    // 需要对数据进行二次处理
    return _handleResponse(result);
  }

  // 处理返回数据结构
  _handleResponse(Response<dynamic> result) {
    if (result.data["code"] == GlobalVariable.SUCCESS_CODE) {
      // 此时说明请求成功 返回正确的数据
      return result.data["data"];
    }
    PromptAction.showError(result.data["message"]);
    // 提示个消息 使用第三方插件的toast弹出
    throw Exception(result.data["message"]);
  }
}

// 单例导出
final requestDio = RequestDio();
